﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Xml;
using HuaCheng.CommonClass;
using HuaCheng.Model;

namespace HuaCheng.Controller
{
    public class XmlControl
    {
        /// <summary>
        /// 生成xml文件
        /// </summary>
        public static XmlDocument CreateXml(StepSetInfo stepsetInfo)
        {
            //创建一个xml文档
            XmlDocument doc = new XmlDocument();
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "GB2312", null);
            doc.AppendChild(dec);
            //创建根节点
            XmlElement root = doc.CreateElement("root");
            doc.AppendChild(root);
            //创建根节点下config节点
            XmlElement config = doc.CreateElement("config");
            config.SetAttribute("version", "15");
            config.SetAttribute("type", "Step File");
            root.AppendChild(config);
            //创建config节点下Head_Info节点
            XmlNode head = doc.CreateElement("Head_Info");
            config.AppendChild(head);
            XmlElement operate = doc.CreateElement("Operate");
            //标准/专业工步设置
            if (stepsetInfo.TabpageName == "tabPageStandStep")
            {
                operate.SetAttribute("Value", "65");
            }
            else
            {
                operate.SetAttribute("Value", "66");
            }
            head.AppendChild(operate);
            //起始工步
            XmlElement startStep = doc.CreateElement("Start_Step");           
            startStep.SetAttribute("Value", Convert.ToString(stepsetInfo.StartStep));
            head.AppendChild(startStep);
            //创建者
            XmlElement creator = doc.CreateElement("Creator");
            creator.SetAttribute("Value", stepsetInfo.Creator);
            head.AppendChild(creator);
            //电池批号
            XmlElement batteryNum = doc.CreateElement("Battery_Num");
            batteryNum.SetAttribute("Value", stepsetInfo.BatteryNum);
            head.AppendChild(batteryNum);
            //备注
            XmlElement remark = doc.CreateElement("Remark");
            remark.SetAttribute("Value", stepsetInfo.Remark);
            head.AppendChild(remark);
            //工步信息（开始标签）工步个数
            XmlElement stepInfo = doc.CreateElement("Step_Info");
            stepInfo.SetAttribute("Num", Convert.ToString(stepsetInfo.StepList.Count));
            config.AppendChild(stepInfo);
            //遍历表格的每一行，获得每一行工步信息
            for (int i = 0; i < stepsetInfo.StepList.Count; i++)
            {
                //nodeInfo存每一行（每个工步）的信息
                Dictionary<string, string> nodeInfo = new Dictionary<string, string>();
                //获取每个工步的所有属性值（每一列的信息）
                System.Reflection.PropertyInfo[] properties = stepsetInfo.StepList[i].GetType().GetProperties();
                Type type = stepsetInfo.StepList[i].GetType();
                //遍历每一列，获得每个单元格的值
                for (int j = 0; j < properties.Length; j++)
                {
                    //得到每个属性的值
                    object column = type.GetProperty(properties[j].Name).GetValue(stepsetInfo.StepList[i]);
                    if (column != null)
                    {
                        if (properties[j].Name != "Dt" && properties[j].Name != "ChildList" && properties[j].Name != "ProtCondition" && properties[j].Name != "ProtSelect" )
                        {
                            nodeInfo.Add(properties[j].Name, Convert.ToString(column));
                        }
                    }
                    else
                    {
                        nodeInfo.Add(properties[j].Name, "none");
                    }
                }
                //工况数据
                object columnDt = type.GetProperty("Dt").GetValue(stepsetInfo.StepList[i]);
                if (columnDt != null)
                {
                    string strDt = Collection.ToJson((DataTable)columnDt);
                    nodeInfo.Add("Dt", strDt);
                }
                else
                {
                    nodeInfo["Dt"] = "none";
                }
                //保护条件勾选状态
                object columnSel = type.GetProperty("ProtSelect").GetValue(stepsetInfo.StepList[i]);
                if (columnSel != null)
                {
                    string strSel = JsonHelper.Serialize(columnSel);
                    nodeInfo.Add("ProtSelect", strSel);
                }
                else
                {
                    nodeInfo["ProtSelect"] = "none";
                }
                //保护条件
                object columnCon = type.GetProperty("ProtCondition").GetValue(stepsetInfo.StepList[i]);
                if (columnCon != null)
                {
                    string strCon = JsonHelper.Serialize(columnCon);
                    nodeInfo.Add("ProtCondition", strCon);
                }
                else
                {
                    nodeInfo["ProtCondition"] = "none";
                }
                //step节点代表每一个工步
                XmlElement step = null;
                ////Record节点
                //XmlElement parameter = null;
                ////Record节点下的Main节点
                //XmlElement parameterMain = null;
                //Limit节点（Limit节点中存工步设置的表格中的信息）
                XmlElement limit = null;
                //Limit下的Main节点
                XmlElement limitMain = null;
                //Limit下的Other节点
                XmlElement limitOther = null;
                //当前行的工步名称
                string stepType = stepsetInfo.StepList[i].StepName;
                if (stepType != "")
                {
                    //生成Step节点
                    //Step[i]的Step_ID
                    string stepid = Convert.ToString(i + 1);
                    //生成step节点
                    step = doc.CreateElement("Step" + stepid);
                    step.SetAttribute("Step_ID", stepid);
                    //Step[i]的Step_Type
                    step.SetAttribute("Step_Type", stepType);
                    stepInfo.AppendChild(step);
                    //生成Limit节点（Limit节点中存工步设置的表格中的信息）
                    limit = doc.CreateElement("Limit");
                    step.AppendChild(limit);
                    //生成Limit下的Main节点
                    limitMain = doc.CreateElement("Main");
                    limit.AppendChild(limitMain);
                    foreach (string key in nodeInfo.Keys)
                    {
                        if (key != "Mode" && key != "Magnification" && key != "Dt" && key != "ChildList" && key != "Path" && key != "ProtSelect" && key != "ProtCondition" && key != "CircNum" && key != "StartStep" && key != "Creator" && key != "BatteryNum" && key != "Remark")
                        {
                            //将属性名称作为节点名称在Main节点下创建子节点
                            XmlElement mainChild = doc.CreateElement(key);
                            //给子节点赋初值
                            mainChild.SetAttribute("Is_Select", "0");
                            mainChild.SetAttribute("Value", "0");
                            //每一行的根据实际情况给子节点赋值
                            if (nodeInfo[key] != "none"  && stepType != "循环" && stepType != "斜坡工况" && stepType != "脉冲工况")
                            {
                                mainChild.SetAttribute("Is_Select", "1");
                                mainChild.SetAttribute("Value", nodeInfo[key]);
                            }
                            limitMain.AppendChild(mainChild);
                        }
                    }
                    //生成Limit下的Other节点
                    limitOther = doc.CreateElement("Other");
                    limit.AppendChild(limitOther);
                    //生成Other节点下的子节点
                    //Start_Step节点
                    XmlElement start_step = doc.CreateElement("Start_Step");
                    start_step.SetAttribute("Is_Select", "0");
                    start_step.SetAttribute("Value", "0");
                    limitOther.AppendChild(start_step);
                    //Cycle_Count节点
                    XmlElement cycle_count = doc.CreateElement("Cycle_Count");
                    cycle_count.SetAttribute("Is_Select", "0");
                    cycle_count.SetAttribute("Value", "0");
                    limitOther.AppendChild(cycle_count);
                    //Mode节点
                    XmlElement mode = doc.CreateElement("Mode");
                    mode.SetAttribute("Is_Select", "0");
                    mode.SetAttribute("Value", "0");
                    limitOther.AppendChild(mode);
                    //Magnification节点
                    XmlElement magnification = doc.CreateElement("Magnification");
                    magnification.SetAttribute("Is_Select", "0");
                    magnification.SetAttribute("Value", "0");
                    limitOther.AppendChild(magnification);
                    //Condition_Data节点
                    XmlElement condition_data = doc.CreateElement("Condition_Data");
                    condition_data.SetAttribute("Is_Select", "0");
                    condition_data.SetAttribute("Value", "0");
                    limitOther.AppendChild(condition_data);
                    //Path节点
                    XmlElement path = doc.CreateElement("Path");
                    path.SetAttribute("Is_Select", "0");
                    path.SetAttribute("Value", "0");
                    limitOther.AppendChild(path);
                    //Con_Unit节点
                    XmlElement conunit = doc.CreateElement("Con_Unit");
                    conunit.SetAttribute("Is_Select", "0");
                    conunit.SetAttribute("Value", "0");
                    limitOther.AppendChild(conunit);
                    //Time_Unit节点
                    XmlElement timeunit = doc.CreateElement("Time_Unit");
                    timeunit.SetAttribute("Is_Select", "0");
                    timeunit.SetAttribute("Value", "0");
                    limitOther.AppendChild(timeunit);
                    //Protect_Selct节点
                    XmlElement protect_select = doc.CreateElement("Protect_Select");
                    protect_select.SetAttribute("Is_Select", "0");
                    protect_select.SetAttribute("Value", "0");
                    limitOther.AppendChild(protect_select);
                    //Protect_Condition节点
                    XmlElement protect_condition = doc.CreateElement("Protect_Condition");
                    protect_condition.SetAttribute("Is_Select", "0");
                    protect_condition.SetAttribute("Value", "0");
                    limitOther.AppendChild(protect_condition);
                    //参数设置部分
                    if(nodeInfo["ProtSelect"]!=null)
                    {
                        protect_select.SetAttribute("Is_Select", "1");
                        protect_select.SetAttribute("Value", nodeInfo["ProtSelect"]);
                    }
                    if (nodeInfo["ProtCondition"] != null)
                    {
                        protect_condition.SetAttribute("Is_Select", "1");
                        protect_condition.SetAttribute("Value", nodeInfo["ProtCondition"]);
                    }
                    //Param1节点
                    XmlElement paramone = doc.CreateElement("Param1");
                    paramone.SetAttribute("Is_Select", "1");
                    if (stepsetInfo.TabpageName == "tabPageStandStep")
                    {
                        paramone.SetAttribute("Value", "65");
                    }
                    else
                    {
                        paramone.SetAttribute("Value", "66");
                    }
                    limitOther.AppendChild(paramone);
                    //当工步类型是“循环”，设置循环开始工步和循环次数
                    if (stepType == "循环")
                    {
                        start_step.SetAttribute("Is_Select", "1");
                        start_step.SetAttribute("Value", nodeInfo["Voltage"]);
                        cycle_count.SetAttribute("Is_Select", "1");
                        cycle_count.SetAttribute("Value", nodeInfo["Cap"]);
                    }
                    //当工步类型是脉冲工况，斜坡工况
                    if (stepType == "脉冲工况" || stepType == "斜坡工况")
                    {
                        mode.SetAttribute("Is_Select", "1");
                        mode.SetAttribute("Value", nodeInfo["Mode"]);
                        magnification.SetAttribute("Is_Select", "1");
                        magnification.SetAttribute("Value", nodeInfo["Magnification"]);
                        condition_data.SetAttribute("Is_Select", "1");
                        condition_data.SetAttribute("Value", nodeInfo["Dt"]);
                        path.SetAttribute("Is_Select", "1");
                        path.SetAttribute("Value", nodeInfo["Path"]);
                        conunit.SetAttribute("Is_Select", "1");
                        conunit.SetAttribute("Value", nodeInfo["ConUnit"]);
                        timeunit.SetAttribute("Is_Select", "1");
                        timeunit.SetAttribute("Value", nodeInfo["TimeUnit"]);
                    }
                    //当工步下有“如果”子节点或者“记录条件”子节点
                    if (stepsetInfo.StepList[i].ChildList != null)
                    {
                        //获取当前工步下子节点总个数
                        int childStepSum = stepsetInfo.StepList[i].ChildList.Count;
                        //“如果工步”的个数
                        int ifCount = 0;
                        //“记录条件工步”的个数
                        int recordCount = 0;
                        //一个“如果工步”中的四个属性
                        List<string> ifSet = new List<string>() { "If_Condition", "If_Operator", "If_Judgment", "If_Goto" };
                        //xml中所有“如果工步”将四个属性分别列举的信息
                        List<XmlElement> ifchildSet = new List<XmlElement>();
                        //一个“记录条件工步”中的六个属性
                        List<string> recordSet = new List<string>() { "Record_Condition", "Greater_Than", "Less_Than", "Time_Interval", "Voltage_Interval", "Current_Interval" };
                        //xml中所有“记录条件工步”将六个属性分别列举的信息
                        List<XmlElement> recordchildSet = new List<XmlElement>();
                        //遍历当前工步下的二级工步
                        for (int c = 0; c < childStepSum; c++)
                        {
                            Type childType = stepsetInfo.StepList[i].ChildList[c].GetType();
                            //获得二级工步的所有属性
                            //System.Reflection.PropertyInfo[] childProperties = childType.GetProperties();
                            List<string> childIfProperties = new List<string>() { "JumpCond", "JumpOperator", "JumpValue", "JumpTo" };
                            List<string> childReProperties = new List<string>() { "RecordCond", "CondLower", "CondUpper", "TimeInterval", "VolInterval", "CurrInterval" };
                            //若当前遍历的二级工步为“如果”，将信息写入其所属工步的Other节点下对应的子节点中
                            if (stepsetInfo.StepList[i].ChildList[c].ChildStepName == "如果")
                            {
                                //循环创建“如果工步”的四个属性为名字的节点并赋值
                                for (int d = 0; d < 4; d++)
                                {
                                    //创建以属性名和“如果工步”的序号拼接所得字符串为名字的节点
                                    XmlElement otherifChild = doc.CreateElement(ifSet[d] + ifCount);
                                    //给节点赋值
                                    otherifChild.SetAttribute("Is_Select", "1");
                                    //otherifChild.SetAttribute("Value", Convert.ToString(childProperties[d + 1].GetValue(stepsetInfo.StepList[i].ChildList[c])));
                                    otherifChild.SetAttribute("Value", Convert.ToString(childType.GetProperty(childIfProperties[d]).GetValue(stepsetInfo.StepList[i].ChildList[c])));
                                    ifchildSet.Add(otherifChild);
                                    limitOther.AppendChild(otherifChild);
                                }
                                ifCount++;
                            }
                            //若当前遍历的二级工步为“记录条件”，将信息写入其所属工步的Other节点下对应的子节点中
                            else if (stepsetInfo.StepList[i].ChildList[c].ChildStepName == "记录条件")
                            {
                                //循环创建“记录条件工步”的六个属性为名字的节点并赋值
                                for (int e = 0; e < 6; e++)
                                {
                                    //创建以属性名和“记录条件工步”的序号拼接所得字符串为名字的节点
                                    XmlElement otherrecordChild = doc.CreateElement(recordSet[e] + recordCount);
                                    //给节点赋值
                                    otherrecordChild.SetAttribute("Is_Select", "1");
                                    otherrecordChild.SetAttribute("Value", Convert.ToString(childType.GetProperty(childReProperties[e]).GetValue(stepsetInfo.StepList[i].ChildList[c])));
                                    recordchildSet.Add(otherrecordChild);
                                    limitOther.AppendChild(otherrecordChild);
                                }
                                recordCount++;
                            }
                        }
                    }
                }
            }
            return doc;
        }
        /// <summary>
        /// 读取解析xml文件
        /// </summary>
        public static StepSetInfo LoadData(Xmloperation xmlop)
        {
            StepSetInfo ssiObtain = new StepSetInfo();
            //整个表格信息
            List<StepInfo> tmpList = new List<StepInfo>();
            //获取root下的子节点
            XmlElement configNode = xmlop.GetTheElement(xmlop.Doc.DocumentElement, "config");
            //获取config下的子节点Head_Info
            XmlElement headinfoNode = xmlop.GetTheElement(configNode, "Head_Info");
            //获取Head_Info下的子节点Operate（标准/专业工步）
            XmlElement operateNode = xmlop.GetTheElement(headinfoNode, "Operate");
            string tabValue = operateNode.Attributes["Value"].Value;
            if (tabValue == "65")
            {
                ssiObtain.TabpageName = "tabPageStandStep";
            }
            else
            {
                ssiObtain.TabpageName = "tabPageUniqueStep";
            }
            //获取起始工步
            XmlElement startstepNode = xmlop.GetTheElement(headinfoNode, "Start_Step");
            ssiObtain.StartStep = Convert.ToInt32(startstepNode.Attributes["Value"].Value);
            //获取创建者
            XmlElement creatorNode = xmlop.GetTheElement(headinfoNode, "Creator");
            ssiObtain.Creator = creatorNode.Attributes["Value"].Value;
            //获取电池批号
            XmlElement batteryNumNode = xmlop.GetTheElement(headinfoNode, "Battery_Num");
            ssiObtain.BatteryNum = batteryNumNode.Attributes["Value"].Value;
            //获取备注
            XmlElement remarkNode = xmlop.GetTheElement(headinfoNode, "Remark");
            ssiObtain.Remark = remarkNode.Attributes["Value"].Value;
            //获取Step_Info节点
            XmlElement stepinfoNode = xmlop.GetTheElement(configNode, "Step_Info");
            //循环获取Step_Info下的Step(i)
            int limitCount = Convert.ToInt32(stepinfoNode.Attributes["Num"].Value);
            for (int i = 0; i < limitCount; i++)
            {
                //表格的每一行的信息
                StepInfo tmpStepinfo = new StepInfo();
                //TreeListNode tmpNode = ssiObtain.Limit.Nodes.Add();
                //获取Step(i)节点
                XmlElement stepNode = xmlop.GetTheElement(stepinfoNode, "Step" + (i + 1));
                if (stepNode != null)
                {
                    //工步ID
                    string stepId = stepNode.Attributes["Step_ID"].Value;
                    //工步名称
                    string stepType = stepNode.Attributes["Step_Type"].Value;
                    //获取Step(i)节点下的Limit节点
                    XmlElement limitNode = xmlop.GetTheElement(stepNode, "Limit");
                    //获取Limit节点下的Main节点
                    XmlElement mainNode = xmlop.GetTheElement(limitNode, "Main");
                    //给表格的当前行赋值
                    foreach (XmlElement el in mainNode.ChildNodes)
                    {
                        if (el.Attributes["Is_Select"].Value == "1")
                        {
                            //Main节点下的子节点名称（StepInfo属性名称或每一列的名称）
                            string columnName = el.Name;
                            //根据属性名称给tmpStepinfo赋值
                            tmpStepinfo.GetType().GetProperty(columnName).SetValue(tmpStepinfo, el.Attributes["Value"].Value, null);
                        }
                    }
                    //获取Limit下的Other节点
                    XmlElement otherNode = xmlop.GetTheElement(limitNode, "Other");
                    //获取Other下的Start_Step节点
                    XmlElement cycleStartstepNode = xmlop.GetTheElement(otherNode, "Start_Step");
                    XmlElement cyclecountNode = xmlop.GetTheElement(otherNode, "Cycle_Count");
                    //获取Other下的Mode节点
                    XmlElement mode = xmlop.GetTheElement(otherNode, "Mode");
                    //获取Other下的Magnification节点
                    XmlElement magnification = xmlop.GetTheElement(otherNode, "Magnification");
                    //获取Other下的Condition_Data节点
                    XmlElement conditionData = xmlop.GetTheElement(otherNode, "Condition_Data");
                    //获取Other下的Path节点
                    XmlElement path = xmlop.GetTheElement(otherNode, "Path");
                    //获取Other下的Con_Unit节点
                    XmlElement conunit = xmlop.GetTheElement(otherNode, "Con_Unit");
                    //获取Other下的Time_Unit节点
                    XmlElement timeunit = xmlop.GetTheElement(otherNode, "Time_Unit");
                    //获取Other下的Prot_Select节点
                    XmlElement protselect = xmlop.GetTheElement(otherNode, "Protect_Select");
                    //获取Other下的Prot_Condition节点
                    XmlElement protcondition = xmlop.GetTheElement(otherNode, "Protect_Condition");
                    //若存在循环工步，则读取循环的起始工步及循环次数
                    if (cycleStartstepNode.Attributes["Is_Select"].Value == "1")
                    {
                        tmpStepinfo.StepNum = stepId;
                        tmpStepinfo.StepName = stepType;
                        tmpStepinfo.StepTime = "起始工步";
                        tmpStepinfo.Voltage = cycleStartstepNode.Attributes["Value"].Value;
                        tmpStepinfo.Current = "循环次数";
                        tmpStepinfo.Cap = cyclecountNode.Attributes["Value"].Value;
                    }
                    //若存在工况，则读取工况的数据、模式和倍率
                    if (mode.Attributes["Is_Select"].Value == "1")
                    {
                        tmpStepinfo.StepNum = stepId;
                        tmpStepinfo.StepName = stepType;
                        DataTable dtData = Collection.ToDataTable(conditionData.Attributes["Value"].Value);
                        tmpStepinfo.Dt = dtData;
                        tmpStepinfo.Mode = mode.Attributes["Value"].Value;
                        tmpStepinfo.Magnification = Convert.ToSingle(magnification.Attributes["Value"].Value);
                        tmpStepinfo.Path = path.Attributes["Value"].Value;
                        tmpStepinfo.ConUnit = conunit.Attributes["Value"].Value;
                        tmpStepinfo.TimeUnit = timeunit.Attributes["Value"].Value;
                    }
                    //若存在“如果工步”或者“记录条件工步”
                    if (otherNode.ChildNodes.Count > 3)
                    {
                        //当前工步的所有二级工步
                        List<ChildStep> childSet = new List<ChildStep>();
                        XmlElement paramNode = xmlop.GetTheElement(otherNode, "Param1");
                        //找到第一个二级工步的第一个属性节点
                        XmlNode nextNode = paramNode.NextSibling;
                        while (nextNode != null)
                        {
                            //二级工步对象
                            ChildStep childStep = new ChildStep();
                            Type type = childStep.GetType();
                            //获取二级工步对象的所有属性
                            //System.Reflection.PropertyInfo[] childProperties = childStep.GetType().GetProperties();
                            List<string> childIfProperties = new List<string>() { "JumpCond", "JumpOperator", "JumpValue", "JumpTo" };
                            List<string> childReProperties = new List<string>() { "RecordCond", "CondLower", "CondUpper", "TimeInterval", "VolInterval", "CurrInterval" };
                            //若该二级工步是“记录条件工步”
                            if (Convert.ToString(nextNode.Name).StartsWith("Record_Condition"))
                            {
                                childStep.ChildStepName = "记录条件";
                                //循环遍历二级工步对象中“记录条件工步”的相关属性
                                for (int w = 5; w < 11; w++)
                                {
                                    //给二级工步对象中“记录条件工步”的相关属性赋值
                                    //childProperties[w].SetValue(childStep, nextNode.Attributes["Value"].Value);
                                    type.GetProperty(childReProperties[w-5]).SetValue(childStep, nextNode.Attributes["Value"].Value);
                                    nextNode = nextNode.NextSibling;
                                }
                                childSet.Add(childStep);
                                continue;
                            }
                            //若该二级工步是“如果工步”
                            else if (Convert.ToString(nextNode.Name).StartsWith("If_Condition"))
                            {
                                childStep.ChildStepName = "如果";
                                //循环遍历二级工步对象中“如果工步”的相关属性
                                for (int w = 1; w < 5; w++)
                                {
                                    //给二级工步对象中“如果工步”的相关属性赋值
                                    type.GetProperty(childIfProperties[w - 1]).SetValue(childStep, nextNode.Attributes["Value"].Value);
                                    nextNode = nextNode.NextSibling;
                                }
                                childSet.Add(childStep);
                                continue;
                            }
                        }
                        tmpStepinfo.ChildList = childSet;
                    }
                    //读取参数设置信息
                    if(protselect.Attributes["Is_Select"].Value=="1")
                    {
                        if (protselect.Attributes["Value"].Value!="none")
                        {
                            tmpStepinfo.ProtSelect = JsonHelper.Deserialize<ProtectSelect>(protselect.Attributes["Value"].Value);
                        }
                        if (protcondition.Attributes["Value"].Value!="none")
                        {
                            tmpStepinfo.ProtCondition = JsonHelper.Deserialize<ProtectCondition>(protcondition.Attributes["Value"].Value);
                        }
                    }
                }
                tmpList.Add(tmpStepinfo);
                
            }
            
            ssiObtain.StepList = tmpList;
            return ssiObtain;
        }
    }
}
